home *** CD-ROM | disk | FTP | other *** search
/ NOVA - For the NeXT Workstation / NOVA - For the NeXT Workstation.iso / Apps / Utilities / Hardware / SCSItools / select.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-26  |  17.9 KB  |  560 lines

  1. /*
  2. This program loads SCSI select page codes
  3. */
  4. /*
  5.                       USE AT YOUR OUR RISK. 
  6.       I NOT NOT BE RESPONSIBLE FOR PROBLEM CAUSED BY THIS PROGRAM.
  7.  
  8. Note that I have only tested these programs on a small number of drives (see PARAMETERS directories). BE CAREFUL, if you do not know what you are doing, then I recommend that you not use it. But it is very useful for those people that do know.
  9.  */
  10.  
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <fcntl.h>
  14. #include <stdio.h>
  15. #include <sys/types.h>
  16. #include <nextdev/scsireg.h>
  17.  
  18. static char *dev_name="/dev/sg0";    /* generic scsi interface */
  19. #define MAX_inq_dat 64
  20. #define MAX_mod_hdr 4
  21. #define MAX_mod_bdf 16
  22. #define MAX_mod_pag 64
  23. #define MAX_mod_dat 64
  24. #define MAX_mod_buf 256
  25.  
  26. int scsi_open(int target, int lun);
  27. int gs_inquiry(int fd, int lun, int clen, u_char *data);
  28. int gs_mode_select(int fd, int lun, int clen, u_char *data);
  29. int gs_mode_sense(int fd, int lun, int ccode, int cfield, int clen, u_char *data);
  30. int gs_request_sense(int fd, int lun);
  31. struct MODBDF {
  32.     u_char data[MAX_mod_bdf];
  33.     u_char mask[MAX_mod_bdf];
  34.     };
  35. struct  MODPAG {
  36.     int flag;
  37.     u_char data[MAX_mod_dat];
  38.     u_char mask[MAX_mod_dat];
  39.     };
  40. u_char inq_dat[MAX_inq_dat];
  41. u_char mod_hdr[MAX_mod_hdr];
  42. u_char mod_buf[MAX_mod_buf];
  43. int    mod_buf_len;
  44. struct MODBDF mod_bdf;
  45. struct MODPAG mod_pag[MAX_mod_pag];
  46.  
  47. main(int argc, char *argv[])
  48. {
  49.     extern int optind;
  50.     extern char *optarg;
  51.  
  52.     char c;
  53.     int mismatch;
  54.     FILE *infile;
  55.     
  56.     int fd;
  57.     int target = -1;
  58.     int lun = -1;
  59.  
  60.     infile = stdin;
  61.     while ((c = getopt(argc, argv, "t:l:f:")) != EOF) {
  62.         switch (c) {
  63.         case 't':
  64.             target = atoi(optarg);
  65.             break;
  66.         case 'l':
  67.             lun = atoi(optarg);
  68.             break;
  69.         case 'f':
  70.             if ( (infile=fopen(optarg, "r")) == NULL) {
  71.                 fprintf(stdout,"Error opening input file");
  72.                 exit(0);
  73.         }
  74.         break;
  75.     default:
  76.             fprintf(stderr,
  77.                 "usage: %s -t<target> [-l<lun>] [-f inputfile]\n",
  78.                 argv[0]);
  79.             exit(1);
  80.         }
  81.     }
  82.     if (target == -1) {
  83.         fprintf(stderr,
  84.             "usage: %s -t<target> [-l<lun>] [-f inputfile]\n",
  85.             argv[0]);
  86.         exit(1);
  87.     }
  88.     if (lun == -1) {
  89.         lun = 0;
  90.     }
  91.     get_input_data(infile);
  92.     if ((fd = scsi_open(target, lun)) < 0) {
  93.         fputs("error opening scsi device\n", stderr);
  94.         exit(1);
  95.     }
  96. /*+start debug+/
  97.     fprintf(stdout,"Target %d, Handle %d, Lun %d\n",target,fd,lun);
  98. /-end debug-*/
  99.     compare_inquire(fd, lun);
  100.     compare_mode_sense(fd, lun);
  101.     write_mode_select(fd, lun);
  102.     exit(0);
  103. }
  104. get_input_data(FILE *input_file)
  105. {
  106.     char line[80];
  107.     int inq_len,mod_len;
  108.     int i,j,data,mask,page;
  109.     int done;
  110.     
  111.     bzero(inq_dat,sizeof(inq_dat));
  112.     bzero(mod_hdr,sizeof(mod_hdr));
  113.     bzero(mod_bdf.data,sizeof(mod_bdf.data));
  114.     bzero(mod_bdf.mask,sizeof(mod_bdf.mask));
  115.     bzero(mod_pag,sizeof(mod_pag));
  116.     done = 1;
  117.     while (! feof(input_file) & done) {
  118.         fgets(line,sizeof(line),input_file);
  119.         line[sizeof(line)-1] = '\0';
  120.         if (!strncmp(line,"#",1)) {
  121.             continue;
  122.         } else if (!strncmp(line,"-ilen",5)) {
  123.             sscanf(&line[5],"%d",&inq_len);
  124.             if (inq_len > MAX_inq_dat) {
  125.                 fprintf(stdout,"inq_len parameter %d greater than max %d\n"
  126.                     ,inq_len,MAX_inq_dat);
  127.             }
  128.         } else if (!strncmp(line,"-idat",5)) {
  129.             sscanf(&line[5],"%d %x",&i,&data);
  130.             if (i > MAX_inq_dat)
  131.             fprintf(stdout,"inq_dat parameter %d greater than max %d\n"
  132.                 ,i,MAX_inq_dat);
  133.             else inq_dat[i] = data & 0xff;
  134.         } else if (!strncmp(line,"-mlen",5)) {
  135.             sscanf(&line[3],"%d",&mod_len);
  136.             if (i > MAX_mod_dat)
  137.             fprintf(stdout,"mlen parameter %d greater than max %d\n"
  138.                 ,mod_len,MAX_mod_dat);
  139.         } else if (!strncmp(line,"-mhdr",5)) {
  140.             sscanf(&line[5],"%d %x %x",&i,&data,&mask);
  141.             if (i > MAX_mod_hdr)
  142.             fprintf(stdout,"mod_hdr parameter %d greater     than max %d\n"
  143.                 ,i,MAX_mod_hdr);
  144.             else {
  145.             mod_hdr[i] = data & 0xff;
  146.         }
  147.     } else if (!strncmp(line,"-mbdf",5)) {
  148.             sscanf(&line[5],"%d %x %x",&i,&data,&mask);
  149.             if (i > MAX_mod_bdf)
  150.             fprintf(stdout,"mod_bdf parameter %d greater than max %d\n"
  151.                 ,i,MAX_mod_bdf);
  152.             else {
  153.             mod_bdf.data[i] = data & 0xff;
  154.             mod_bdf.mask[i] = mask & 0xff;
  155.         }
  156.         } else if (!strncmp(line,"-mp",3)) {
  157.             sscanf(&line[3],"%d %d %x %x",&page,&i,&data,&mask);
  158.             if (page > MAX_mod_pag)
  159.             fprintf(stdout,"page parameter %d greater than max %d\n"
  160.                 ,page,MAX_mod_pag);
  161.             else {
  162.                 mod_pag[page].flag = 1;
  163.                 if (i > MAX_mod_dat)
  164.                 fprintf(stdout,"mod_pag.data parameter %d, for page %d greater than max %d\n"
  165.                 ,i,page,MAX_inq_dat);
  166.             else {
  167.             mod_pag[page].data[i] = data & 0xff;
  168.             mod_pag[page].mask[i] = mask & 0xff;
  169.         }
  170.         }
  171.         } else if (!strncmp(line,"end",3)) {
  172.         fprintf(stdout,"Encountered end statement\n");
  173.         done = 0;
  174.         } else {
  175.         fprintf(stdout,"Invalid input line\n");
  176.         fprintf(stdout,"%s",line);
  177.     }
  178.     }
  179.     fprintf(stdout,"Done reading input\n");                            
  180. }
  181. compare_inquire(int fd, int lun)
  182. {
  183.     u_char new_dat[MAX_inq_dat];
  184.     char c;
  185.     int mismatch;
  186.    
  187.     bzero(new_dat, sizeof(new_dat));
  188.     if(gs_inquiry(fd, lun, sizeof(new_dat), new_dat)) {
  189.         fputs("error in inquiry\n", stderr);
  190.         close(fd);
  191.         exit(1);
  192.     }
  193. /*+start debug+/
  194.     for (mismatch=0; mismatch<inq_dat[4]+5; mismatch++)
  195.         fprintf(stdout," %2.2x",inq_dat[mismatch]);
  196.     fprintf(stdout,"\n");
  197.     for (mismatch=0; mismatch<new_dat[4]+5; mismatch++)
  198.         fprintf(stdout," %2.2x",new_dat[mismatch]);
  199.     fprintf(stdout,"\n");
  200. /-end debug-*/
  201.     inq_dat[inq_dat[4]+5] = '\0';
  202.     new_dat[new_dat[4]+5] = '\0';
  203.     mismatch = 0;
  204.     if (new_dat[0] != inq_dat[0]) {
  205.         fprintf(stdout,"INQUIRY (byte 0)-Peripheral Device types not not match\n");
  206.         fprintf(stdout,"  input=%2x, disk=%2x\n",inq_dat[0], new_dat[0]);
  207.         mismatch = 1;
  208.     }
  209.     if (new_dat[1] != inq_dat[1]) {
  210.         fprintf(stdout,"INQUIRY (byte 1)Device type qualifiers or RMB do not match \n");
  211.         fprintf(stdout,"  input=%2x, disk=%2x\n",inq_dat[1], new_dat[1]);
  212.         mismatch = 1;
  213.     }
  214.     if (new_dat[2] != inq_dat[2]) {
  215.         fprintf(stdout," INQUIRY (byte 2)-ANSI version's do not not match\n");
  216.         fprintf(stdout,"  input=%2x, disk=%2x\n",inq_dat[2], new_dat[2]);
  217.         mismatch = 1;
  218.     }
  219.     if (new_dat[3] != inq_dat[3]) {
  220.         fprintf(stdout,"INQUIRY (byte 3)-Response Data Formats do not not match\n");
  221.         fprintf(stdout,"  input=%2x, disk=%2x\n",inq_dat[3], new_dat[3]);
  222.         mismatch = 1;
  223.     }
  224.     if (new_dat[4] != inq_dat[4]) {
  225.         fprintf(stdout,"INQUIRY (byte 4)-Additional lengths do not match\n");
  226.         fprintf(stdout,"  input=%2x, disk=%2x\n",inq_dat[4], new_dat[4]);
  227.         fprintf(stdout,"  (bytes 8-n)-Additional data\n");
  228.         fprintf(stdout,"  rest of input=\"%s\"\n",&inq_dat[8]);
  229.         fprintf(stdout,"  rest of disk =\"%s\"\n",&new_dat[8]);
  230.         mismatch = 1;
  231.     }
  232.     if (new_dat[5] != inq_dat[5]) {
  233.         fprintf(stdout,"INQUIRY (byte 5)-Request sense lengths do not match\n");
  234.         fprintf(stdout,"  input=%2x, disk=%2x\n",inq_dat[5], new_dat[5]);
  235.         mismatch = 1;
  236.     }
  237.     if (strcmp(&new_dat[8],&inq_dat[8])) {
  238.         fprintf(stdout,"INQUIRY (bytes 8-n)-Additional data does not match\n");
  239.         fprintf(stdout,"  rest of input=\"%s\"\n",&inq_dat[8]);
  240.         fprintf(stdout,"  rest of disk =\"%s\"\n",&new_dat[8]);
  241.         mismatch = 1;
  242.     }
  243.     if (mismatch) {
  244.         if (feof(stdin))
  245.         c = 'n';
  246.         else {
  247.             fprintf(stdout,"Do you wish to continue? [y/n]: ");
  248.         gets(&c);
  249.     }
  250.         if (! (c == 'y' | c == 'Y')) {
  251.             fprintf(stdout,"exiting due to error in SCSI INQUIRY data\n");
  252.             exit(1);
  253.         } else
  254.             fprintf(stdout,"continuing to reselect drive\n");
  255.     }
  256. }
  257. compare_mode_sense(int fd, int lun)
  258. {
  259.     struct MODPAG new_dat;
  260.     char c;
  261.     int mismatch,change,i,j,page,old,new;
  262.     u_char tmpmask;
  263. /* compare header/bdf first, via SCSI MODE SENSE/PAGE 0 of current paramters (1)*/
  264.     bzero(new_dat.data, sizeof(new_dat.data));
  265.     bzero(new_dat.mask, sizeof(new_dat.mask));
  266.     bzero(mod_buf, sizeof(mod_buf));
  267.     mod_buf_len = 0;
  268.     mod_buf[0] = 0;
  269.     if(gs_mode_sense(fd, lun, 0, 1, sizeof(new_dat.mask), new_dat.mask)) {
  270.         fputs("error in MODE SENSE for header (page 0)\n", stderr);
  271.         close(fd);
  272.         exit(1);
  273.     }
  274.     if(gs_mode_sense(fd, lun, 0, 3, sizeof(new_dat.data), new_dat.data)) {
  275.         fputs("error in MODE SENSE for header (page 0)\n", stderr);
  276.         close(fd);
  277.         exit(1);
  278.     }
  279. /*+start debug+/
  280.     for (mismatch=0; mismatch<new_dat.data[0]; mismatch++)
  281.         fprintf(stdout," %2.2x",new_dat.data[mismatch]);
  282.     fprintf(stdout,"\n");
  283.     for (mismatch=0; mismatch<new_dat.data[0]; mismatch++)
  284.         fprintf(stdout," %2.2x",new_dat.mask[mismatch]);
  285.     fprintf(stdout,"\n");
  286. /-end debug-*/
  287.     mismatch = 0;
  288.     change = 0;
  289. /*+start debug+*/
  290.     fprintf(stdout,"Compare header\n");
  291. /*-end debug-*/
  292.     for (i = 1; i <= 3; i++) {
  293.         mod_buf_len++;
  294.         mod_buf[mod_buf_len] = mod_hdr[i];
  295.     }
  296.     if (new_dat.data[1] != mod_hdr[1]) {
  297.         fprintf(stdout,"MODE SENSE (header byte 1)-Medium type does not match\n");
  298.         fprintf(stdout,"  input=%2x, disk=%2x\n",mod_hdr[1], new_dat.data[1]);
  299.         mismatch = 1;
  300.     }
  301.     if (new_dat.data[2] != mod_hdr[2]) {
  302.         fprintf(stdout,"MODE SENSE (header byte 2)-Write protect bit does not match\n");
  303.         fprintf(stdout,"  input=%2x, disk=%2x\n",mod_hdr[2], new_dat.data[2]);
  304.         mismatch = 1;
  305.     }
  306.     if (new_dat.data[3] != mod_hdr[3]) {
  307.         fprintf(stdout,"MODE SENSE (header byte 3)-Block Descriptor Length does not match\n");
  308.         fprintf(stdout,"  input=%2x, disk=%2x\n",mod_hdr[3], new_dat.data[3]);
  309.         mismatch = 1;
  310.     } else for (i = 0; i < new_dat.data[3]; i++) {
  311.         mod_buf_len++;
  312.     tmpmask = mod_bdf.mask[i];
  313.     mod_buf[mod_buf_len] = (mod_bdf.data[i]&tmpmask) | (new_dat.data[i+4]&~tmpmask);
  314.         if ((new_dat.mask[i+4]|mod_bdf.mask[i]) != new_dat.mask[i+4]) {
  315.             fprintf(stdout,"MODE SENSE (BDF byte %4.4d)-input mask not subset of disk mask\n",i);
  316.         fprintf(stdout," input mask=%x, disk mask=%x\n",mod_bdf.mask[i],new_dat.mask[i+4]);
  317.             mismatch = 1;
  318.     }
  319.     if ((mod_bdf.data[i]&mod_bdf.mask[i]) != mod_bdf.data[i]) {
  320.             fprintf(stdout,"MODE SENSE (BDF byte %4.4d)-input value not subset of input mask\n",i);
  321.         fprintf(stdout," input value=%2.2x, input mask=%2.2x\n",mod_bdf.data[i],mod_bdf.mask[i]);
  322.             mismatch = 1;
  323.     }
  324.     if (mod_buf[mod_buf_len] != new_dat.data[i+4]) {
  325.             fprintf(stdout,"MODE SENSE (BDF byte %4.4d)-disk value will be changed\n",i);
  326.         fprintf(stdout," old value=%2.2x, new value=%2.2x\n",new_dat.data[i+4],mod_buf[mod_buf_len]);
  327.             change = 1;
  328.     }
  329.     }
  330. /* compare page codes now, via SCSI MODE SENSE of current paramters (1)*/
  331.     for (page = 0; page < MAX_mod_pag; page++) {
  332.         if (mod_pag[page].flag != 0) {
  333. /*+start debug+*/
  334.         fprintf(stdout,"Compare page %2.2d\n",page);
  335. /*-end debug-*/
  336.             bzero(new_dat.data, sizeof(new_dat.data));
  337.             bzero(new_dat.mask, sizeof(new_dat.mask));
  338.             if(gs_mode_sense(fd, lun, page, 1, sizeof(new_dat.mask), new_dat.mask)) {
  339.                 fprintf(stdout,"MODE SENSE error for page code %d reading masks\n",page);
  340.                 mismatch = 1;
  341.             } else if(gs_mode_sense(fd, lun, page, 3, sizeof(new_dat.data), new_dat.data)) {
  342.                 fprintf(stdout,"MODE SENSE error for page code %d reading data\n",page);
  343.                 mismatch = 1;
  344.             } else {
  345.             i = new_dat.data[3]+4;
  346.             if (new_dat.data[0]+1 == i) {
  347.                 fprintf(stdout,"MODE SENSE (Page %2.2d)-No such page code on disk\n",page);
  348.             mismatch = 1;
  349.             } else if ((new_dat.data[i]&63) != (mod_pag[page].data[0]&63)) {
  350.                 fprintf(stdout,"MODE SENSE (Page %2.2d,byte-0)-Page code does not match\n",page);
  351.             fprintf(stdout
  352.                     ," input value=%2.2x, disk value=%2.2x\n"
  353.                     ,mod_pag[page].data[0],new_dat.data[i]);
  354.             mismatch = 1;
  355.             } else if ((new_dat.data[i]&128) != (mod_pag[page].data[0]&128)) {
  356.                 fprintf(stdout,"MODE SENSE (Page %2.2d,byte-0)-PS bit does not match\n",page);
  357.                 fprintf(stdout
  358.                     ," input value=%2.2x, disk value=%2.2x\n"
  359.                     ,mod_pag[page].data[0],new_dat.data[i]);
  360.             mismatch = 1;
  361.             } else if (new_dat.data[i+1] != mod_pag[page].data[1]) {
  362.                 fprintf(stdout,"MODE SENSE (Page %2.2d,byte-1)-Page length does not match\n",page);
  363.             fprintf(stdout
  364.                     ," input value=%2.2x, disk value=%2.2x\n"
  365.                     ,mod_pag[page].data[1],new_dat.data[i+1]);
  366.             mismatch = 1;
  367.                 } else for (j = 0; j < mod_pag[page].data[1]+2; j++) {
  368.                     mod_buf_len++;
  369.             tmpmask = mod_pag[page].mask[j]&new_dat.mask[i+j];
  370.                 if (j == 0) {
  371.                 mod_buf[mod_buf_len] = mod_pag[page].data[0]&63;
  372.             new_dat.data[i] = new_dat.data[i]&63;
  373.             } else {
  374.                 mod_buf[mod_buf_len] = (mod_pag[page].data[j]&tmpmask) | (new_dat.data[i+j]&~tmpmask);
  375.             }
  376.                    if ((new_dat.mask[i+j]|mod_pag[page].mask[j]) != new_dat.mask[i+j]) {
  377.                     fprintf(stdout
  378.                     ,"MODE SENSE (Page %2.2d byte %d)-input mask not subset of disk mask\n"
  379.                     ,page,j);
  380.                 fprintf(stdout
  381.                     ," input mask=%2.2x, disk mask=%2.2x\n"
  382.                     ,mod_pag[page].mask[j],new_dat.mask[i+j]);
  383.                     mismatch = 1;
  384.             } else if ((mod_pag[page].data[j]&mod_pag[page].mask[j]) != mod_pag[page].data[j]) {
  385.                         fprintf(stdout,
  386.                     "MODE SENSE (Page %2.2d byte %d)-input value not subset of input mask\n"
  387.                     ,page,j);
  388.                     fprintf(stdout,
  389.                     " input value=%2.2x, input mask=%2.2x\n"
  390.                     ,mod_pag[page].data[j],mod_pag[page].mask[j]);
  391.                     mismatch = 1;
  392.             } else if (mod_buf[mod_buf_len] != new_dat.data[i+j]) {
  393.                     fprintf(stdout,"MODE SENSE (Page %2.2d byte %d)-disk value will be changed\n",page,j);
  394.                 fprintf(stdout," old value=%2.2x, new value=%2.2x\n",new_dat.data[i+j],mod_buf[mod_buf_len]);
  395.                     change = 1;
  396.             }
  397.             }
  398.         }
  399.     }
  400.     }
  401.     if (mismatch) {
  402.         if (feof(stdin))
  403.         c = 'n';
  404.         else {
  405.             fprintf(stdout,"Do you wish to continue? [y/n]: ");
  406.             gets(&c);
  407.     }
  408.         if (! (c == 'y' | c == 'Y')) {
  409.             fprintf(stdout,"exiting due to error in SCSI SENSE MODE data\n");
  410.             exit(1);
  411.         } else
  412.             fprintf(stdout,"continuing to SELECT MODE drive\n");
  413.     }
  414. }
  415. write_mode_select(int fd, int lun)
  416. {
  417.     char c;
  418.     int i;
  419.     mod_buf[0] = 0;
  420.     mod_buf_len++;
  421.     fprintf(stdout,"mod buffer output\n");
  422.     for (i = 0; i < mod_buf_len; i++) {
  423.         fprintf(stdout,"%2.2x %2.2x\n",i,mod_buf[i]);
  424.     }
  425.     if (feof(stdin))
  426.     c = 'n';
  427.     else {
  428.         fprintf(stdout,"Do you wish to continue with the scsi mode select of drive? [y/n]: ");
  429.         gets(&c);
  430.     }
  431.     if (! (c == 'y' | c == 'Y')) {
  432.         fprintf(stdout,"exiting without doing SCSI SELECT MODE\n");
  433.         exit(1);
  434.     } else {
  435.         fprintf(stdout,"continuing with doing SCSI SELECT MODE\n");
  436.         if(gs_mode_select(fd, lun, mod_buf_len, mod_buf)) {
  437.             fputs("error in mode select\n", stderr);
  438.             close(fd);
  439.             exit(1);
  440.     } else {
  441.         fputs("exiting SCSI SELECT MODE successfully completed\n",stderr);
  442.     }
  443.     }
  444. }   
  445. int scsi_open(int target, int lun)
  446. {
  447.     struct scsi_adr sa;
  448.     int fd;
  449.  
  450.     if ((fd = open(dev_name, O_RDWR)) < 0) {
  451.         fprintf(stderr,"\nCould not open %s\n",dev_name);
  452.         return(-1);
  453.     }
  454.  
  455.     sa.sa_target = target;
  456.     sa.sa_lun = lun;
  457.     if (ioctl(fd,SGIOCSTL,&sa) < 0) {
  458.         fprintf(stderr,"Error setting target %d lun %d\n",target,lun);
  459.         close(fd);
  460.         return(-1);
  461.     }
  462.  
  463.     if(gs_request_sense(fd, lun)) {        /* clear unit attention */
  464.         close(fd);
  465.         return(-1);
  466.     }
  467.     return(fd);
  468. }
  469.  
  470. int gs_inquiry(int fd, int lun, int clen, u_char *data)
  471. {
  472.     struct scsi_req sr;
  473.     struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
  474.  
  475.     bzero((char *)&sr, sizeof(sr));
  476.     cdbp->c6_opcode = C6OP_INQUIRY;
  477.     cdbp->c6_lun    = lun;
  478.     cdbp->c6_lba    = 0;
  479.     cdbp->c6_len    = clen;
  480.     sr.sr_dma_dir    = SR_DMA_RD;
  481.     sr.sr_addr    = (caddr_t)data;
  482.     sr.sr_dma_max    = clen;
  483.     sr.sr_ioto    = 10;
  484.     return(do_ioc(fd, &sr));
  485. }
  486.  
  487. int gs_mode_select(int fd, int lun, int clen, u_char *ddat)
  488. {
  489.     struct scsi_req sr;
  490.     struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
  491.  
  492.     bzero((char *)&sr, sizeof(sr));
  493.     cdbp->c6_opcode = C6OP_MODESELECT;
  494.     cdbp->c6_lun    = lun;
  495.     cdbp->c6_lba    = 0x110000 ; /* use pf=1 & sp=1 to save parameters */
  496. /*    cdbp->c6_lba    = (( (pf&1) << 21) | (sp&1) << 17);*/
  497.     cdbp->c6_len    = clen;
  498.     sr.sr_dma_dir    = SR_DMA_WR;
  499.     sr.sr_addr    = (caddr_t)ddat;
  500.     sr.sr_dma_max    = clen;
  501.     sr.sr_ioto    = 10;
  502.     return(do_ioc(fd, &sr));
  503. }
  504.  
  505.  
  506. int gs_mode_sense(int fd, int lun, int ccode, int cfield, int clen, u_char *data)
  507. {
  508.     struct scsi_req sr;
  509.     struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
  510.  
  511.     bzero((char *)&sr, sizeof(sr));
  512.     cdbp->c6_opcode = C6OP_MODESENSE;
  513.     cdbp->c6_lun    = lun;
  514.     cdbp->c6_lba    = ((cfield << 14) & 0xc000) | ((ccode << 8) & 0x3f00);
  515.     cdbp->c6_len    = clen;
  516.     sr.sr_dma_dir    = SR_DMA_RD;
  517.     sr.sr_addr    = (caddr_t)data;
  518.     sr.sr_dma_max    = clen;
  519.     sr.sr_ioto    = 10;
  520.     return(do_ioc(fd, &sr));
  521. }
  522.  
  523.  
  524. int do_ioc(int fd, struct scsi_req *sr)
  525. {
  526.     if (ioctl(fd, SGIOCREQ, sr) < 0) {
  527.         perror("ioctl(SGIOCREQ)");
  528.         return(-1);
  529.     }
  530.     if(sr->sr_io_status) {
  531.         fprintf(stderr,"sr_io_status = 0x%02X\n",sr->sr_io_status);
  532.         if(sr->sr_io_status == SR_IOST_CHKSV) {
  533.             fprintf(stderr,
  534.                 "sense key = 0x%02X, sense code = 0x%02X\n",
  535.                 sr->sr_esense.er_sensekey,
  536.                 sr->sr_esense.er_addsensecode);
  537.         }
  538.         fprintf(stderr,"SCSI status = 0x%02X\n", sr->sr_scsi_status);
  539.         return(-1);
  540.     }
  541.     return(0);
  542. }
  543.  
  544. int gs_request_sense(int fd, int lun)
  545. {
  546.     struct scsi_req sr;
  547.     struct cdb_6 *cdbp = &sr.sr_cdb.cdb_c6;
  548.     u_char sbuf[128];
  549.  
  550.     bzero((char *)&sr, sizeof(sr));
  551.     cdbp->c6_opcode = C6OP_REQSENSE;
  552.     cdbp->c6_lun    = lun;
  553.     cdbp->c6_len    = 18;
  554.     sr.sr_dma_dir    = SR_DMA_RD;
  555.     sr.sr_addr    = (caddr_t)sbuf;
  556.     sr.sr_dma_max    = 128;
  557.     sr.sr_ioto    = 10;
  558.     return(do_ioc(fd, &sr));
  559. }
  560.